package mazeBueno2Obfuscado;

import java.util.ArrayList;
import java.util.Random;



public class Maze {
	private int logColisiones = 0;
	private int width;
	private int height;
	private boolean[][] map;
	private Random rnd;

	public Maze(int width, int height) {
		this.width = width;
		this.height = height;
		//System.out.println((width*2-1) + " " + (height*2-1));
		
	}
	
	
	public void generateMultipleChoice(long seed, int whiteNoise) {
		generate(seed);
		Random b = new Random();
		for (int i = 0; i < this.width*2-1; i++) {
			for (int j = 0; j < this.height*2-1;j++) {
				if ((i+j)%2 != 0)
					if (b.nextInt(whiteNoise) == 0)
						this.map[i][j] = true;
			}
		}
	}
	public void generate(long seed) {
		System.out.println("Generando nuevo laberinto (" + this.width + "," + this.height + ")con semilla: " + seed);
		long time = System.currentTimeMillis();
		logColisiones = 0;
		
		this.map = new boolean[width*2-1][height*2-1];
		rnd = new Random(seed);
		double prob = rnd.nextDouble();
		
		System.out.println("Probabilidad de parar: " + prob);
		
		this.map[(width)/2][(height)/2] = true;
		generate((width)/2,(height)/2,1/*prob*/);
		//this.map[xStart*2][yStart*2] = true;
		//generate(xStart*2,yStart*2);
		//TODO CONTADOR DE COLISIONES
		System.out.println("Colisiones: " + this.getColisiones());
		System.out.println("Tiempo: " + (System.currentTimeMillis() - time) + "ms");
	}
	
	private void generate(int xx, int yy, double pr) {
		int x = xx, y = yy, xO, yO, d = rnd.nextInt(4), n = 0;
		ArrayList<Point> P = new ArrayList<Point>(); Point p; P.add(new Point(x,y,d));
		while(true) {
			p = P.get(P.size()-1); x = p.x(); y = p.y(); d = p.d();
			if (!this.nextPlace(x,y,d)) {
				if (n * pr >= 1) { swap(P,rnd.nextInt(P.size())); n = 0;}
				else {	yO = (d%2+1)*(-1+d); xO = (d%2)*(-2+d);
						map[x+xO][y+yO] = true; map[x+xO*2][y+yO*2] = true;
						P.add(new Point(x+xO,y+yO,rnd.nextInt(4))); n++; }}
			else {n = 0; if (p.nD() == p.gSD()) P.remove(P.size()-1);}
			if (P.size()== 0) break;}
	}


	private void swap(ArrayList<Point> a, int rand) {
		Point tmp = a.get(rand);
		a.set(rand, a.get(a.size()-1));
		a.set(a.size()-1,tmp);
	}

	private boolean nextPlace(int x, int y, int dir) {
		switch(dir) {
		case 0: {
			if (y == 0)
				return true;
			return this.map[x][y-2];
		}
		case 1: {
			if (x >= this.width*2-2)
				return true;
			return this.map[x+2][y];
		}
		case 2: {
			if (y >= this.height*2-2)
				return true;
			return this.map[x][y+2];
		}
		case 3: {
			if (x == 0)
				return true;
			return this.map[x-2][y];
		}
		}
		return true;
	}
	private boolean nextSquare(int x, int y, int dir) {
		switch(dir) {
		case 0: {
			if (y == 0)
				return false;
			return this.map[x][y-1];
		}
		case 1: {
			if (x >= this.width*2-2)
				return false;
			return this.map[x+1][y];
		}
		case 2: {
			if (y >= this.height*2-2)
				return false;
			return this.map[x][y+1];
		}
		case 3: {
			if (x == 0)
				return false;
			return this.map[x-1][y];
		}
		}
		return true;
	}
	public boolean getSquare(int x, int y) {
		return this.map[x][y];
	}
	private int getColisiones() {
		int colisiones = 0;
		for (int i = 0; i < this.width; i++) 
			for (int j = 0; j < this.height; j++) {
				int cont = 0;
				for (int k = 0; k < 4; k++) {
					if (nextSquare(i*2,j*2,k))
						cont++;
				}
				if (cont == 1)
					colisiones++;
			}
		return colisiones;
	}
	
	
}
